﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using Furion.DataEncryption;
using Org.BouncyCastle.Crypto.Engines;
using System.Security.Cryptography;

#endregion

namespace Neto.Encry;

/// <summary>
///     加密解密类扩展
///     虽然Furion已有对应扩展，但是要分别引用不同命名空间，比较麻烦，所以外面再套了一层。
/// </summary>
public static class EncryExtension
{
    /// <summary>
    ///     计算字符串的 MD5 哈希值。
    /// </summary>
    /// <param name="str">要计算哈希值的字符串。</param>
    /// <returns>字符串的 MD5 哈希值。</returns>
    public static string ToMd5(this string str)
    {
        if (string.IsNullOrWhiteSpace(str)) throw new ArgumentNullException(nameof(str), "输入字符串不能为空。");
        return MD5Encryption.Encrypt(str);
    }

    #region AES

    /// <summary>
    ///     使用 AES 算法加密字符串。
    /// </summary>
    /// <param name="text">需要加密的字符串。</param>
    /// <param name="skey">密钥（长度必须为 16、24 或 32 字节）。</param>
    /// <returns>加密后的字符串。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串或密钥为空，则抛出此异常。</exception>
    public static string ToAESEncrypt(this string text, string skey)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(skey)) throw new ArgumentNullException(nameof(skey), "AES 密钥不能为空。");
        return AESEncryption.Encrypt(text, skey);
    }

    /// <summary>
    ///     使用 AES 算法解密字符串。
    /// </summary>
    /// <param name="text">需要解密的字符串。</param>
    /// <param name="skey">密钥（长度必须为 16、24 或 32 字节）。</param>
    /// <returns>解密后的字符串。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串或密钥为空，则抛出此异常。</exception>
    public static string ToAESDecrypt(this string text, string skey)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(skey)) throw new ArgumentNullException(nameof(skey), "AES 密钥不能为空。");
        return AESEncryption.Decrypt(text, skey);
    }

    #endregion AES

    #region RSA

    /// <summary>
    ///     使用 RSA 算法加密字符串。
    /// </summary>
    /// <param name="text">需要加密的字符串。</param>
    /// <param name="publicKey">公钥。</param>
    /// <param name="keySize">密钥长度（必须为 2048 到 16384，并且是 8 的倍数），默认为 2048。</param>
    /// <returns>加密后的字符串。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串或公钥为空，则抛出此异常。</exception>
    public static string ToRsaEncyrpt(this string text, string publicKey, int keySize = 2048)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(publicKey)) throw new ArgumentNullException(nameof(publicKey), "公钥不能为空。");
        return RSAEncryption.Encrypt(text, publicKey, keySize);
    }

    /// <summary>
    ///     使用 RSA 算法解密字符串。
    /// </summary>
    /// <param name="text">需要解密的字符串。</param>
    /// <param name="privateKey">私钥。</param>
    /// <param name="keySize">密钥长度（必须为 2048 到 16384，并且是 8 的倍数），默认为 2048。</param>
    /// <returns>解密后的字符串。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串或私钥为空，则抛出此异常。</exception>
    public static string ToRsaDeCrypt(this string text, string privateKey, int keySize = 2048)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(privateKey)) throw new ArgumentNullException(nameof(privateKey), "私钥不能为空。");
        return RSAEncryption.Decrypt(text, privateKey, keySize);
    }

    /// <summary>
    ///     使用 RSA 算法对字符串进行签名。
    /// </summary>
    /// <param name="text">明文内容。</param>
    /// <param name="halg">哈希算法，例如 SHA256。</param>
    /// <param name="privateKey">私钥。</param>
    /// <returns>签名内容。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串、哈希算法或私钥为空，则抛出此异常。</exception>
    public static string ToRsaSign(this string text, string halg, string privateKey)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(halg)) throw new ArgumentNullException(nameof(halg), "哈希算法不能为空。");
        if (string.IsNullOrWhiteSpace(privateKey)) throw new ArgumentNullException(nameof(privateKey), "私钥不能为空。");

        using var rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(privateKey);

        var encryptedData = rsa.SignData(Encoding.UTF8.GetBytes(text), halg);
        return Convert.ToBase64String(encryptedData);
    }

    /// <summary>
    ///     验证 RSA 签名。
    /// </summary>
    /// <param name="text">明文内容。</param>
    /// <param name="halg">哈希算法，例如 SHA256。</param>
    /// <param name="publicKey">公钥。</param>
    /// <param name="sign">签名内容。</param>
    /// <returns>如果签名有效，则返回 true；否则返回 false。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串、哈希算法、公钥或签名为空，则抛出此异常。</exception>
    public static bool ToRsaSignVerify(this string text, string halg, string publicKey, string sign)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(halg)) throw new ArgumentNullException(nameof(halg), "哈希算法不能为空。");
        if (string.IsNullOrWhiteSpace(publicKey)) throw new ArgumentNullException(nameof(publicKey), "公钥不能为空。");
        if (string.IsNullOrWhiteSpace(sign)) throw new ArgumentNullException(nameof(sign), "签名不能为空。");

        using var rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(publicKey);

        return rsa.VerifyData(Encoding.UTF8.GetBytes(text), halg, Convert.FromBase64String(sign));
    }

    /// <summary>
    ///     过滤RSA公钥/私钥内容中的前后缀和换行符
    /// </summary>
    /// <param name="content">RSA公钥或私钥内容</param>
    /// <returns>过滤后的内容</returns>
    public static string ToRsaContentFormatClear(this string content)
    {
        if (string.IsNullOrWhiteSpace(content)) return content;

        // 移除标准的RSA私钥前后缀
        content = content.Replace("-----BEGIN RSA PRIVATE KEY-----", "");
        content = content.Replace("-----END RSA PRIVATE KEY-----", "");

        // 移除非标准的RSA私钥前后缀
        content = content.Replace("-----BEGIN PRIVATE KEY-----", "");
        content = content.Replace("-----END PRIVATE KEY-----", "");

        // 移除标准的RSA公钥前后缀
        content = content.Replace("-----BEGIN PUBLIC KEY-----", "");
        content = content.Replace("-----END PUBLIC KEY-----", "");

        // 移除非标准的RSA公钥前后缀
        content = content.Replace("-----BEGIN RSA PUBLIC KEY-----", "");
        content = content.Replace("-----END RSA PUBLIC KEY-----", "");

        // 移除换行符和回车符
        content = content.Replace("\r", "");
        content = content.Replace("\n", "");

        return content.Trim();
    }

    #endregion RSA

    #region DESC

    /// <summary>
    ///     使用 DES 算法加密字符串。
    /// </summary>
    /// <param name="text">需要加密的字符串。</param>
    /// <param name="skey">密钥（长度必须为 8 字节）。</param>
    /// <returns>加密后的字符串。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串或密钥为空，则抛出此异常。</exception>
    public static string ToDESCEncrypt(this string text, string skey)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(skey)) throw new ArgumentNullException(nameof(skey), "DES 密钥不能为空。");
        return DESEncryption.Encrypt(text, skey);
    }

    /// <summary>
    ///     使用 DES 算法解密字符串。
    /// </summary>
    /// <param name="text">需要解密的字符串。</param>
    /// <param name="skey">密钥（长度必须为 8 字节）。</param>
    /// <returns>解密后的字符串。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串或密钥为空，则抛出此异常。</exception>
    public static string ToDESCDecrypt(this string text, string skey)
    {
        if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException(nameof(text), "输入字符串不能为空。");
        if (string.IsNullOrWhiteSpace(skey)) throw new ArgumentNullException(nameof(skey), "DES 密钥不能为空。");
        return DESEncryption.Decrypt(text, skey);
    }

    #endregion DESC

    #region SHA

    #region SHA1

    /// <summary>
    ///     计算字符串的 SHA1 哈希值。
    /// </summary>
    /// <param name="str">字符串。</param>
    /// <returns>字符串的 SHA1 哈希值。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串为空，则抛出此异常。</exception>
    public static string ToSha1(this string str)
    {
        if (string.IsNullOrWhiteSpace(str)) throw new ArgumentNullException(nameof(str), "输入字符串不能为空。");

        using var sha1 = SHA1.Create();
        var bytes_sha1_in = Encoding.UTF8.GetBytes(str);
        var bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in);
        return BitConverter.ToString(bytes_sha1_out).Replace("-", "");
    }

    #endregion SHA1

    #region SHA256

    /// <summary>
    ///     计算字符串的 SHA256 哈希值。
    /// </summary>
    /// <param name="str">字符串。</param>
    /// <returns>字符串的 SHA256 哈希值。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串为空，则抛出此异常。</exception>
    public static string ToSha256(this string str)
    {
        if (string.IsNullOrWhiteSpace(str)) throw new ArgumentNullException(nameof(str), "输入字符串不能为空。");

        using var sha256 = SHA256.Create();
        var bytes_sha256_in = Encoding.UTF8.GetBytes(str);
        var bytes_sha256_out = sha256.ComputeHash(bytes_sha256_in);
        return BitConverter.ToString(bytes_sha256_out).Replace("-", "");
    }

    #endregion SHA256

    #region SHA384

    /// <summary>
    ///     计算字符串的 SHA384 哈希值。
    /// </summary>
    /// <param name="str">字符串。</param>
    /// <returns>字符串的 SHA384 哈希值。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串为空，则抛出此异常。</exception>
    public static string ToSha384(this string str)
    {
        if (string.IsNullOrWhiteSpace(str)) throw new ArgumentNullException(nameof(str), "输入字符串不能为空。");

        using var sha384 = SHA384.Create();
        var bytes_sha384_in = Encoding.UTF8.GetBytes(str);
        var bytes_sha384_out = sha384.ComputeHash(bytes_sha384_in);
        return BitConverter.ToString(bytes_sha384_out).Replace("-", "");
    }

    #endregion SHA384

    #region SHA512

    /// <summary>
    ///     计算字符串的 SHA512 哈希值。
    /// </summary>
    /// <param name="str">字符串。</param>
    /// <returns>字符串的 SHA512 哈希值。</returns>
    /// <exception cref="ArgumentNullException">如果输入字符串为空，则抛出此异常。</exception>
    public static string ToSha512(this string str)
    {
        if (string.IsNullOrWhiteSpace(str)) throw new ArgumentNullException(nameof(str), "输入字符串不能为空。");

        using var sha512 = SHA512.Create();
        var bytes_sha512_in = Encoding.UTF8.GetBytes(str);
        var bytes_sha512_out = sha512.ComputeHash(bytes_sha512_in);
        return BitConverter.ToString(bytes_sha512_out).Replace("-", "");
    }

    #endregion SHA512

    #endregion SHA


    #region SM2为非对称加密，基于ECC

    /// <summary>
    ///     使用SM2算法对数据进行签名。
    /// </summary>
    /// <param name="data">要签名的数据字节数组。</param>
    /// <param name="privateKey">私钥字节数组。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名后的字节数组。</returns>
    public static byte[] ToSM2Sign(byte[] data, byte[] privateKey, byte[]? userId = null)
    {
        return SM2.Sign(data, privateKey, userId);
    }

    /// <summary>
    ///     使用SM2算法对字符串数据进行签名。
    /// </summary>
    /// <param name="data">要签名的字符串数据。</param>
    /// <param name="privateKey">私钥字符串。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名后的Base64编码字符串。</returns>
    public static string ToSM2Sign(this string data, string privateKey, string userId)
    {
        return SM2.Sign(data, privateKey, userId);
    }

    /// <summary>
    ///     验证使用SM2算法生成的签名。
    /// </summary>
    /// <param name="data">原始数据字节数组。</param>
    /// <param name="publicKey">公钥字节数组。</param>
    /// <param name="dataSigned">签名的字节数组。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名是否有效的布尔值。</returns>
    public static bool ToSM2VerifySign(byte[] data, byte[] publicKey, byte[] dataSigned, byte[]? userId = null)
    {
        return SM2.VerifySign(data, publicKey, dataSigned, userId);
    }

    /// <summary>
    ///     验证使用SM2算法生成的签名（字符串形式）。
    /// </summary>
    /// <param name="data">原始字符串数据。</param>
    /// <param name="publicKey">公钥字符串。</param>
    /// <param name="dataSigned">签名的Base64编码字符串。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名是否有效的布尔值。</returns>
    public static bool ToSM2VerifySign(this string data, string publicKey, string dataSigned, string userId)
    {
        return SM2.VerifySign(data, publicKey, dataSigned, userId);
    }

    /// <summary>
    ///     使用SM2算法对数据哈希进行签名。
    /// </summary>
    /// <param name="data">要签名的数据字节数组。</param>
    /// <param name="privateKey">私钥字节数组。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名后的字节数组。</returns>
    public static byte[] ToSM2SignByDataHash(byte[] data, byte[] privateKey, byte[]? userId = null)
    {
        return SM2.SignByDataHash(data, privateKey, userId);
    }

    /// <summary>
    ///     使用SM2算法对字符串数据哈希进行签名。
    /// </summary>
    /// <param name="data">要签名的字符串数据。</param>
    /// <param name="privateKey">私钥字符串。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名后的Base64编码字符串。</returns>
    public static string ToSM2SignByDataHash(this string data, string privateKey, string userId)
    {
        return SM2.SignByDataHash(data, privateKey, userId);
    }

    /// <summary>
    ///     验证使用SM2算法对数据哈希生成的签名。
    /// </summary>
    /// <param name="data">原始数据字节数组。</param>
    /// <param name="publicKey">公钥字节数组。</param>
    /// <param name="dataSigned">签名的字节数组。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名是否有效的布尔值。</returns>
    public static bool ToSM2VerifySignByDataHash(byte[] data, byte[] publicKey, byte[] dataSigned,
        byte[]? userId = null)
    {
        return SM2.VerifySignByDataHash(data, publicKey, dataSigned, userId);
    }

    /// <summary>
    ///     验证使用SM2算法对数据哈希生成的签名（字符串形式）。
    /// </summary>
    /// <param name="data">原始字符串数据。</param>
    /// <param name="publicKey">公钥字符串。</param>
    /// <param name="dataSigned">签名的Base64编码字符串。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <returns>签名是否有效的布尔值。</returns>
    public static bool ToSM2VerifySignByDataHash(this string data, string publicKey, string dataSigned, string userId)
    {
        return SM2.VerifySignByDataHash(data, publicKey, dataSigned, userId);
    }

    /// <summary>
    ///     使用SM2算法对数据进行加密。
    /// </summary>
    /// <param name="data">要加密的数据字节数组。</param>
    /// <param name="publicKey">公钥字节数组。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <param name="mode">加密模式（默认为C1C3C2）。</param>
    /// <returns>加密后的字节数组。</returns>
    public static byte[] ToSM2Encrypt(byte[] data, byte[] publicKey, byte[]? userId = null,
        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2)
    {
        return SM2.Encrypt(data, publicKey, userId, mode);
    }

    /// <summary>
    ///     使用SM2算法对字符串数据进行加密。
    /// </summary>
    /// <param name="data">要加密的字符串数据。</param>
    /// <param name="publicKey">公钥字符串。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <param name="mode">加密模式（默认为C1C3C2）。</param>
    /// <returns>加密后的Base64编码字符串。</returns>
    public static string ToSM2Encrypt(this string data, string publicKey, string userId,
        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2)
    {
        return SM2.Encrypt(data, publicKey, userId, mode);
    }

    /// <summary>
    ///     使用SM2算法对数据进行解密。
    /// </summary>
    /// <param name="dataEncrypted">要解密的数据字节数组。</param>
    /// <param name="privateKey">私钥字节数组。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <param name="mode">加密模式（默认为C1C3C2）。</param>
    /// <returns>解密后的字节数组。</returns>
    public static byte[] ToSM2Decrypt(byte[] dataEncrypted, byte[] privateKey, byte[]? userId = null,
        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2)
    {
        return SM2.Decrypt(dataEncrypted, privateKey, userId, mode);
    }

    /// <summary>
    ///     使用SM2算法对字符串数据进行解密。
    /// </summary>
    /// <param name="dataEncrypted">要解密的Base64编码字符串。</param>
    /// <param name="privateKey">私钥字符串。</param>
    /// <param name="userId">用户ID（可选）。</param>
    /// <param name="mode">加密模式（默认为C1C3C2）。</param>
    /// <returns>解密后的Base64编码字符串。</returns>
    public static string ToSM2Decrypt(this string dataEncrypted, string privateKey, string userId,
        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2)
    {
        return SM2.Decrypt(dataEncrypted, privateKey, userId, mode);
    }

    #endregion SM2

    #region SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。

    /// <summary>
    ///     使用SM3算法对数据进行哈希。
    /// </summary>
    /// <param name="data">要哈希的数据字节数组。</param>
    /// <returns>哈希后的字节数组。</returns>
    public static byte[] ToSM3Hash(this byte[] data)
    {
        return SM3.Hash(data);
    }

    /// <summary>
    ///     使用SM3算法对字符串数据进行哈希。
    /// </summary>
    /// <param name="data">要哈希的字符串数据。</param>
    /// <returns>哈希后的Base64编码字符串。</returns>
    public static string ToSM3HashBase64(this string data)
    {
        return SM3.ToHashBase64(data);
    }

    /// <summary>
    ///     使用SM3算法对字符串数据进行哈希。
    /// </summary>
    /// <param name="data">要哈希的字符串数据。</param>
    /// <returns>哈希后的Base32编码字符串。</returns>
    public static string ToSM3HashBase32(this string data)
    {
        return SM3.ToHashBase32(data);
    }

    /// <summary>
    ///     使用SM3算法对字符串数据进行哈希。
    /// </summary>
    /// <param name="data">要哈希的字符串数据。</param>
    /// <returns>哈希后的Hex编码字符串。</returns>
    public static string ToSM3HashHex(this string data)
    {
        return SM3.ToHashHex(data);
    }

    /// <summary>
    ///     使用SM3算法对数据进行带密钥的哈希（HMAC）。
    /// </summary>
    /// <param name="data">要哈希的数据字节数组。</param>
    /// <param name="key">密钥字节数组。</param>
    /// <returns>HMAC后的字节数组。</returns>
    public static byte[] ToSM3Hash(this byte[] data, byte[] key)
    {
        return SM3.Hash(data, key);
    }

    /// <summary>
    ///     使用SM3算法对字符串数据进行带密钥的哈希（HMAC）。
    /// </summary>
    /// <param name="data">要哈希的字符串数据。</param>
    /// <param name="key">密钥字符串。</param>
    /// <returns>HMAC后的Base64编码字符串。</returns>
    public static string ToSM3HashBase64(this string data, string key)
    {
        return SM3.ToHashBase64(data, key);
    }

    /// <summary>
    ///     使用SM3算法对字符串数据进行带密钥的哈希（HMAC）。
    /// </summary>
    /// <param name="data">要哈希的字符串数据。</param>
    /// <param name="key">密钥字符串。</param>
    /// <returns>HMAC后的Base32编码字符串。</returns>
    public static string ToSM3HashBase32(this string data, string key)
    {
        return SM3.ToHashBase32(data, key);
    }

    /// <summary>
    ///     使用SM3算法对字符串数据进行带密钥的哈希（HMAC）。
    /// </summary>
    /// <param name="data">要哈希的字符串数据。</param>
    /// <param name="key">密钥字符串。</param>
    /// <returns>HMAC后的Hex编码字符串。</returns>
    public static string ToSM3HashHex(this string data, string key)
    {
        return SM3.ToHashHex(data, key);
    }

    #endregion SM3


    #region SM4 无线局域网标准的分组数据算法。对称加密，密钥长度和分组长度均为128位。

    /// <summary>
    ///     使用SM4算法对数据进行CBC模式加密。
    /// </summary>
    /// <param name="data">要加密的数据字节数组。</param>
    /// <param name="key">密钥字节数组。</param>
    /// <param name="iv">初始化向量（IV）字节数组。</param>
    /// <returns>加密后的字节数组。</returns>
    public static byte[] ToSM4CBCEncrypt(this byte[] data, byte[] key, byte[] iv)
    {
        return SM4.CBCEncrypt(data, key, iv);
    }

    /// <summary>
    ///     使用SM4算法对字符串数据进行CBC模式加密。
    /// </summary>
    /// <param name="data">要加密的字符串数据。</param>
    /// <param name="key">密钥字符串。</param>
    /// <param name="iv">初始化向量（IV）字符串。</param>
    /// <returns>加密后的Base64编码字符串。</returns>
    public static string ToSM4CBCEncrypt(this string data, string key, string iv)
    {
        return SM4.CBCEncrypt(data, key, iv);
    }

    /// <summary>
    ///     使用SM4算法对数据进行CBC模式解密。
    /// </summary>
    /// <param name="data">要解密的数据字节数组。</param>
    /// <param name="key">密钥字节数组。</param>
    /// <param name="iv">初始化向量（IV）字节数组。</param>
    /// <returns>解密后的字节数组。</returns>
    public static byte[] ToSM4CBCDecrypt(this byte[] data, byte[] key, byte[] iv)
    {
        return SM4.CBCDecrypt(data, key, iv);
    }

    /// <summary>
    ///     使用SM4算法对字符串数据进行CBC模式解密。
    /// </summary>
    /// <param name="data">要解密的Base64编码字符串。</param>
    /// <param name="key">密钥字符串。</param>
    /// <param name="iv">初始化向量（IV）字符串。</param>
    /// <returns>解密后的Base64编码字符串。</returns>
    public static string ToSM4CBCDecrypt(this string data, string key, string iv)
    {
        return SM4.CBCDecrypt(data, key, iv);
    }

    #endregion SM4
}